#include "connection.h"
#include "channel.h"
#include "socket.h"
#include <cassert>
#include <cstring>
#include <unistd.h>

Connection::Connection(int fd, EventLoop *loop) {
    socket_ = std::make_unique<Socket>();
    socket_->set_fd(fd);
    if (loop != nullptr) {
        channel_ = std::make_unique<Channel>(fd, loop);
        channel_->EnableRead();
        channel_->EnableET();
    }

    state_ = State::Connected;
}

Connection::~Connection() {}

RC Connection::Read() {
    if (state_ != State::Connected) {
        perror("Connection is not connected, can not read");
        return RC_CONNECTION_ERROR;
    }
    assert(state_ == State::Connected && "connection state is disconnected!");

    int sockfd = socket_->fd();
    rx_len = 0;
    while (true) {
        // 使用非阻塞IO，读取客户端buffer，一次读取buf大小数据，直到全部读取完毕
        ssize_t bytes_read = read(sockfd, read_buf_ + rx_len, sizeof(read_buf_) - rx_len);
        if (bytes_read > 0) {
            rx_len += bytes_read;
        } else if (bytes_read == -1 && errno == EINTR) { // 程序正常中断、继续读取
            printf("continue reading\n");
            continue;
        } else if (bytes_read == -1 &&
                   ((errno == EAGAIN) ||
                    (errno == EWOULDBLOCK))) { // 非阻塞IO，这个条件表示数据全部读取完毕
            break;
        } else if (bytes_read == 0) { // EOF，客户端断开连接
            printf("read EOF, client fd %d disconnected\n", sockfd);
            state_ = State::Closed;
            Close();
            break;
        } else {
            printf("Other error on client fd %d\n", sockfd);
            state_ = State::Closed;
            Close();
            break;
        }
    }
    return RC_SUCCESS;
}

int Connection::send(const uint8_t *str, int len) {
    send_buf_ = reinterpret_cast<const char *>(str);
    tx_len = len;

    if (state_ != State::Connected) {
        perror("Connection is not connected, can not write");
        return RC_CONNECTION_ERROR;
    }

    int sockfd = socket_->fd();

    int data_size = tx_len;
    int data_left = data_size;
    while (data_left > 0) {
        ssize_t bytes_write = write(sockfd, send_buf_ + data_size - data_left, data_left);
        if (bytes_write == -1 && errno == EINTR) {
            printf("continue writing\n");
            continue;
        }
        if (bytes_write == -1 && errno == EAGAIN) {
            continue;
        }
        if (bytes_write == -1) {
            printf("Other error on client fd %d\n", sockfd);
            state_ = State::Closed;
            break;
        }
        data_left -= bytes_write;
    }
    return data_size;
}

void Connection::Business() {
    Read();
    on_recv_(this);
}

void Connection::set_delete_connection(std::function<void(int)> const &fn) {
    delete_connectioin_ = std::move(fn);
}

void Connection::set_on_recv(std::function<void(Connection *)> const &fn) {
    on_recv_ = std::move(fn);
    std::function<void()> bus = std::bind(&Connection::Business, this);
    channel_->set_read_callback(bus);
}

void Connection::Close() { delete_connectioin_(socket_->fd()); }

Connection::State Connection::state() const { return state_; }

Socket *Connection::socket() const { return socket_.get(); }

char *Connection::read_buf() { return read_buf_; }
const char *Connection::send_buf() { return send_buf_; }

int Connection::get_recv_len() { return rx_len; }
